package cn.schoolwow.flow.monitor.module.initial.flow;

import cn.schoolwow.flow.monitor.domain.FlowMonitorOption;
import cn.schoolwow.flow.monitor.entity.FlowLog;
import cn.schoolwow.flow.monitor.util.FlowMonitorUtil;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;

public class UpdateFlowLogFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(UpdateFlowLogFlow.class);

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setUpdateFlowLog(flowContext);
        setStatus(flowContext);
        updateFlowLog(flowContext);
    }

    @Override
    public String name() {
        return "流程执行完毕更新流程日志";
    }

    private void setUpdateFlowLog(FlowContext flowContext){
        FlowLog flowLog = flowContext.checkInstanceData(FlowLog.class);

        try {
            //保存流程执行数据
            {
                Map<String,Object> flowExecuteDataMap = flowContext.getFlowExecuteDataMap();
                flowLog.setContextData(JSON.parseObject(JSON.toJSONString(flowExecuteDataMap)));
            }
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            flowContext.printFlowDataRange();
            flowLog.setException(FlowMonitorUtil.exception2String(e));
            flowLog.setExceptionMessage(e.getMessage());
        }

        flowLog.setFlowNameList(flowContext.getFlowArray().toJSONString());
        flowLog.setFlowTrace(flowContext.getFlowTrace());
        flowLog.setBrokenReason(flowContext.getBrokenReason());
        Exception e = flowContext.getFlowException();
        if(null!=e){
            flowLog.setException(FlowMonitorUtil.exception2String(e));
            flowLog.setExceptionMessage(e.getMessage());
        }
        flowLog.setEndTime(LocalDateTime.now());
        Duration duration = Duration.between(flowLog.getStartTime(), flowLog.getEndTime());
        flowLog.setConsumeTime(duration.toMillis());
    }

    private void setStatus(FlowContext flowContext){
        FlowLog flowLog = flowContext.checkInstanceData(FlowLog.class);

        if(null==flowContext.getBrokenReason()&&null==flowContext.getFlowException()){
            flowLog.setStatus(1);
        }else if(null!=flowContext.getFlowException()){
            flowLog.setStatus(2);
        }else if(null!=flowContext.getBrokenReason()){
            flowLog.setStatus(3);
        }else{
            //无法判断
            flowLog.setStatus(0);
        }
    }

    private void updateFlowLog(FlowContext flowContext){
        FlowLog flowLog = flowContext.checkInstanceData(FlowLog.class);

        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);
        FlowMonitorOption flowMonitorOption = applicationContext.getBean(FlowMonitorOption.class);

        String sql = flowMonitorOption.dao.stopRecord();
        flowLog.setSql(sql);

        boolean shouldSaveFlowLog = flowContext.getData("是否保存流程日志",boolean.class,true);
        if(shouldSaveFlowLog){
            flowMonitorOption.dao.partColumn(
                    "contextData","exception","exceptionMessage","flowNameList","flowTrace",
                    "brokenReason","endTime","consumeTime","sql"
            ).update(flowLog);
        }
    }
}
